import asyncio
import os
import aiohttp
import requests
from urllib.parse import urlparse, unquote
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys


class DownloadManager(QThread):
    progressUpdated = pyqtSignal(str, float)  # Signal to update progress
    downloadFinished = pyqtSignal()  # Signal to indicate download completion

    def __init__(self, concurrency, parent=None):
        super().__init__(parent)
        self.concurrency = concurrency
        self.download_tasks = []
        self.current_downloads = set()
        self.total_bytes_expected = 0
        self.total_bytes_downloaded = 0

    async def download(self, url, save_path, filename):
        if filename is None:
            filename = self.get_filename_from_url(url)

        if not filename:
            print(f"无法获取 {url} 的文件名")
            return

        save_path = os.path.join(save_path, filename)

        # 创建保存路径的目录
        os.makedirs(os.path.dirname(save_path), exist_ok=True)
        try:
            async with self.semaphore:
                async with aiohttp.ClientSession(
                    connector=aiohttp.TCPConnector(force_close=False)
                ) as session:
                    async with session.get(url) as response:
                        total_size = int(response.headers.get("Content-Length", 0))
                        self.total_bytes_expected += total_size  # 增加总体大小

                        bytes_downloaded = 0

                        with open(save_path, "wb") as f:
                            async for chunk in response.content.iter_any():
                                if chunk:
                                    f.write(chunk)
                                    bytes_downloaded += len(chunk)

                                    # 计算总体进度
                                    total_progress = (
                                        (
                                            self.total_bytes_downloaded
                                            / self.total_bytes_expected
                                        )
                                        * 100
                                        if self.total_bytes_expected > 0
                                        else 0
                                    )

                                    # # 单个文件进度
                                    # progress = (
                                    #     (bytes_downloaded / total_size) * 100
                                    #     if total_size > 0
                                    #     else 0
                                    # )

                                    # if self.progress_callback1:
                                    #     self.progress_callback1(total_progress)
                                    self.progressUpdated.emit(total_progress)

                                    self.total_bytes_downloaded += len(chunk)
        except Exception as e:
            print(f"下载 {url} 时发生其他错误: {str(e)}")
            raise  # 如果是其他错误，直接向上层抛出异常

        self.donwloaded += 1

        percentage = (self.donwloaded / len(self.download_tasks)) * 100
        percentage_rounded = round(percentage, 2)
        # if self.progress_callback:
        #     self.progress_callback("", str(percentage_rounded))
        # print(
        #     "当前进度" + str(len(self.download_tasks)) + "占" + str(percentage_rounded)
        # )

        # 完成下载后的回调
        if self.complete_callback:
            self.complete_callback(filename)

    def get_filename_from_url(self, url):
        try:
            response = requests.head(url, allow_redirects=True)
            if "Content-Disposition" in response.headers:
                content_disposition = response.headers["Content-Disposition"]
                filename = content_disposition.split("filename=")[1]
                return unquote(filename.strip("\"'"))
            else:
                parsed_url = urlparse(url)
                filename = os.path.basename(parsed_url.path)
                return filename
        except Exception as e:
            print(f"获取文件名出错: {str(e)}")
            return None

    def start_downloads(self):
        print("下载初始化")
        self.total_bytes_expected = 0
        self.total_bytes_downloaded = 0

        for url, save_path, filename in self.download_tasks:
            download_coroutine = self.download(url, save_path, filename)
            self.current_downloads.add(download_coroutine)

        asyncio.run(asyncio.gather(*self.current_downloads))

        # Clear download tasks and current downloads set
        self.download_tasks.clear()
        self.current_downloads.clear()

        self.downloadFinished.emit()  # Signal download completion

    def add_download_task(self, url, save_path, filename=None):
        self.download_tasks.append((url, save_path, filename))


class DownloadWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.download_manager = DownloadManager(6)

        # Connect signals to slot functions
        self.download_manager.progressUpdated.connect(self.update_progress)
        self.download_manager.downloadFinished.connect(self.download_finished)
        self.start_downloads()
        print("创建陈工")

        # ... (Create UI elements)

    def start_downloads(self):
        self.download_manager.add_download_task(
            "https://wirelesscdn-download.xuexi.cn/publish/xuexi_android/latest/xuexi_android_10002068.apk",
            "downloads",
            "zzz.zip",
        )
        self.download_manager.add_download_task(
            "https://dldir1.qq.com/qqfile/qq/PCQQ9.7.17/QQ9.7.17.29225.exe",
            "downloads",
            "qq.apk",
        )
        self.download_manager.start()

    def update_progress(self, progress):
        print(f"下载总进度: {progress:.2f}%")

    def download_finished(self):
        print("完成")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = DownloadWidget()
    widget.show()
    sys.exit(app.exec())
